package Server_Netty.TCP;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * TCP的粘拆包机制
 * 头两个字节的数据表示数据包的长度，后面为真实需要数据
 * DataLen = FirstByte * 256 + SecondByte
 * */

public class TCPBytesDataProtocolDecoder extends ByteToMessageDecoder {
    //自定义协议的长度表示 FirstByte，SecondByte，共占用两个字节
    //所以最短数据长度=2
    public final short BASE_LENGTH=2;
    public static final Logger LOGGER= LoggerFactory.getLogger(TCPServer.class);

    /**
     * synchronized关键字是用来控制线程同步
     * 多线程环境下,控制该代码段不被多个线程同时执行*/
    @Override
    synchronized protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception {
        int buflen =byteBuf.readableBytes();  //数据包的总数据量
        //可读数据量必须大于基本长度
        if(buflen < BASE_LENGTH) {
            return;
        }
        else {
            //记录包头开始的index
            byteBuf.markReaderIndex();
            //取前2个字节的数据
            short DataLen = byteBuf.readShort();
            //计算粘拆包头表示的数据量
            short DataLen_LowByte = (short)(DataLen % 256);
            short DataLen_HighByte = (short)(DataLen / 256);
            short Data_Len = (short)(DataLen_HighByte * 256 + DataLen_LowByte);

            //判断数据包数据量是否到齐(是否还有部分数据未到)
            if(byteBuf.readableBytes() < Data_Len) {
                //还原读指针
                byteBuf.resetReaderIndex();
                return;
            }
            else {
                //读取data数据
                byte[] TcpData = new byte[Data_Len];
                byteBuf.readBytes(TcpData);  //读取指定长度内容,存入TcpData

                //封装成类对象
                TCPBytesDataProtocol protocol = new TCPBytesDataProtocol(Data_Len, TcpData);
                list.add(protocol);
            }
        }
    }
}
